#include "Floor.h"
#include <iostream>

Floor::Floor(float s)
{
    auto size = s / 2.0f;
    using namespace Nitro::Renderer;

    struct FloorVertex
    {
        glm::vec3 position;
        glm::vec2 texCoord;
    } vertices[] = {
        {{size, 0.f, size}, {size, size}},
        {{size, 0.f, -size}, {size, 0.f}},
        {{-size, 0.f, -size}, {0.f, 0.f}},
        {{-size, 0.f, size}, {0.f, size}},
    };
    uint32_t indices[] = {0, 1, 2, 0, 2, 3};

    BufferDescriptor bufferDesc;
    bufferDesc.bindFlags = BindFlags::VertexBuffer;
    bufferDesc.size = sizeof(vertices);
    bufferDesc.appendAttribute(offsetof(FloorVertex, position),
                               sizeof(FloorVertex), Format::RGB32Float);
    bufferDesc.appendAttribute(offsetof(FloorVertex, texCoord),
                               sizeof(FloorVertex), Format::RG32Float);
    vertexBuffer = CreateBuffer(bufferDesc, vertices);

    TextureDescriptor2D texDesc;
    texDesc.minFilter = TextureFilter::LinearMipmapLinear;
    texDesc.magFilter = TextureFilter::Linear;
    texDesc.wrappingX = TextureWrapping::Repeat;
    texDesc.wrappingY = TextureWrapping::Repeat;
    int w, h, n;
    auto data = stbi_load("floor.jpg", &w, &h, &n, 3);
    SourceImageDescriptor srcDesc;
    srcDesc.data = data;
    srcDesc.format = Format::RGB8UInt;
    srcDesc.width = w;
    srcDesc.height = h;
    texture = CreateTexture2D(texDesc, srcDesc);
    texture.generateMipmap();
    stbi_image_free(data);

    ShaderDescriptor shaderDesc;
    shaderDesc.source = R"delimiter(
    #version 450 core
    in vec3 position;
    in vec2 textureCoord;
    out vec2 texCoord;
    uniform mat4 viewProjectionMatrix;
    void main() {
        gl_Position = viewProjectionMatrix * vec4(position, 1.0f);
        texCoord = textureCoord;
    }
    )delimiter";
    shaderDesc.sourceType = ShaderSourceType::SourceCode;
    shaderDesc.type = ShaderType::VertexShader;
    vs = CreateShader(shaderDesc);
    if (vs.hasReport())
    {
        std::cout << vs.getReport() << '\n';
    }
    shaderDesc.source = R"delimiter(
    #version 450 core
    in vec2 texCoord;
    out vec4 fragColor;
    uniform sampler2D floorTexture;
    void main() {
        fragColor = texture(floorTexture, texCoord);
    }
    )delimiter";
    shaderDesc.sourceType = ShaderSourceType::SourceCode;
    shaderDesc.type = ShaderType::FragmentShader;
    fs = CreateShader(shaderDesc);
    if (fs.hasReport())
    {
        std::cout << fs.getReport() << '\n';
    }

    PipelineDescriptor pipelineDesc;
    pipelineDesc.vertexShader = vs;
    pipelineDesc.fragmentShader = fs;
    pipelineDesc.drawMode = DrawMode::TriangleFan;
    pipeline = CreatePipeline(pipelineDesc);
    std::cout << pipeline.getReport() << '\n';
}

void Floor::render()
{
    updateMatrix();
    pipeline.activate();
    pipeline.setUniform("viewProjectionMatrix", viewProjectionMatrix);
    glBindTexture(GL_TEXTURE_2D, texture.id);
    pipeline.setVertexBuffer(vertexBuffer);
    pipeline.draw(0, 4);
}